export class GlobalEvent {}
export class KeyboardEvent extends GlobalEvent {
  button: number;
  type: KeyEventName;
  constructor(action: KeyEventId, button: number) {
    super();
    this.button = button;
    this.type = keyEventName[action];
  }
  valueOf() {
    return this;
  }
  toString() {
    return JSON.stringify(this);
  }
}

export class MouseEvent extends GlobalEvent {
  x: number;
  y: number;
  button: MouseEventId;
  type: MouseEventName;
  constructor(button: MouseEventId, x: number, y: number) {
    super();
    this.x = x;
    this.y = y;
    this.button = button;
    this.type = mouseEventName[button];
  }
  valueOf() {
    return this;
  }
  toString() {
    return JSON.stringify(this);
  }
}
export class MouseMoveEvent extends MouseEvent {}
export class LeftButtonDownEvent extends MouseEvent {}
export class LeftButtonUpEvent extends MouseEvent {}
export class LeftButtonDoubleClickEvent extends MouseEvent {}
export class RightButtonDownEvent extends MouseEvent {}
export class RightButtonUpEvent extends MouseEvent {}
export class RightButtonDoubleClickEvent extends MouseEvent {}
export class MiddleButtonDownEvent extends MouseEvent {}
export class MiddleButtonUpEvent extends MouseEvent {}
export class MiddleButtonDoubleClickEvent extends MouseEvent {}
export class MouseWheel extends MouseEvent {
  value: number;
  constructor(button: MouseEventId, x: number, y: number, value: number) {
    super(button, x, y);
    this.value = value;
  }
}
export const mouseEventName = {
  0: 'MouseMoveEvent',
  1: 'LeftButtonDownEvent',
  2: 'LeftButtonUpEvent',
  3: 'LeftButtonDoubleClickEvent',
  4: 'RightButtonDownEvent',
  5: 'RightButtonUpEvent',
  6: 'RightButtonDoubleClickEvent',
  7: 'MiddleButtonDownEvent',
  8: 'MiddleButtonUpEvent',
  9: 'MiddleButtonDoubleClickEvent',
  10: 'MouseWheel',
} as const;
export const keyEventName = {
  0: 'KeyDownEvent',
  1: 'KeyPressEvent',
  2: 'KeyUpEvent',
} as const;
export type MouseEventId = keyof typeof mouseEventName;
export type MouseEventName = (typeof mouseEventName)[MouseEventId];
export type KeyEventId = keyof typeof keyEventName;
export type KeyEventName = (typeof keyEventName)[KeyEventId];
export class KeyDownEvent extends KeyboardEvent {}
export class KeyPressEvent extends KeyboardEvent {}
export class KeyUpEvent extends KeyboardEvent {}

function getKeyboardEvent(action: KeyEventId, value: number) {
  return new exportValue[keyEventName[action]](action, value);
}

function getMouseEvent(action: MouseEventId, x: number, y: number, value: number) {
  return new exportValue[mouseEventName[action]](action, x, y, value);
}
export function getEvent(type: number, action: number, value: number, x: number, y: number) {
  if (type === 0) {
    return getKeyboardEvent(action as KeyEventId, value);
  } else if (type === 1) {
    return getMouseEvent(action as MouseEventId, x, y, value);
  } else {
    throw new Error('Invalid event type: ' + type);
  }
}
const exportValue = {
  GlobalEvent,
  KeyboardEvent,
  MouseEvent,
  MouseMoveEvent,
  LeftButtonDownEvent,
  LeftButtonUpEvent,
  LeftButtonDoubleClickEvent,
  RightButtonDownEvent,
  RightButtonUpEvent,
  RightButtonDoubleClickEvent,
  MiddleButtonDownEvent,
  MiddleButtonUpEvent,
  MiddleButtonDoubleClickEvent,
  MouseWheel,
  KeyDownEvent,
  KeyPressEvent,
  KeyUpEvent,
  getEvent,
} as const;
